package com.github.chain.admin.server.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.github.chain.admin.common.constants.AdminConst;
import com.github.chain.admin.common.domain.*;
import com.github.chain.admin.common.enums.AdminErrorMsgEnum;
import com.github.framework.core.exception.Ex;
import com.github.framework.core.page.DataPage;
import com.github.chain.admin.common.request.RoleRequest;
import com.github.chain.admin.server.dao.*;
import com.github.chain.admin.server.service.RoleService;
import com.github.framework.core.Result;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class RoleServiceImpl implements RoleService {

    private static final Logger LOGGER = LoggerFactory.getLogger(RoleServiceImpl.class);


    @Resource
    private RoleDao roleDao;

    @Resource
    private UserDao userDao;

    @Resource
    private UserRoleDao userRoleDao;

    @Resource
    private RoleMenuDao roleMenuDao;

    @Resource
    private MenuDao menuDao;

    @Override
    public Result<Boolean> findRoleByUserId(Long userId) {

        LOGGER.info("查询用户对应的角色,userId:{}",userId);

        if (null == userId){
            LOGGER.error("查询用户对应的角色userId为空!");
            return Result.fail(AdminErrorMsgEnum.REQUEST_PARAMS_IS_EMPTY);
        }

        User user = userDao.findUserByUserId(userId);

        if (null == user){
            LOGGER.error("根据用户id查询对应用户数据不存在,userId:{}",userId);
            return Result.fail(AdminErrorMsgEnum.CURRENT_USER_NOT_EXIST);
        }

        List<UserRole> userRoleList = userRoleDao.findUserRoleByUserId(userId);

        List<Long> roleIdList = new ArrayList<>();
       if (CollectionUtils.isEmpty(userRoleList)){
           LOGGER.error("根据用户id查询对应的用户角色数据为空code:001,userId:{}",userId);
           return Result.fail(AdminErrorMsgEnum.CURRENT_USER_NOT_EXIST);
       }

        userRoleList.forEach(u -> {
            Long roleId = u.getRoleId();
            roleIdList.add(roleId);
        });

        List<Role> roleList = roleDao.findRoleByRoleIds(roleIdList);

        if (CollectionUtils.isEmpty(roleList)){
            LOGGER.error("根据用户角色查询对应的角色数据为空,userId:{},roleIdsList:{}",userId,roleIdList);
            return Result.fail(AdminErrorMsgEnum.CURRENT_USER_NOT_EXIST);
        }

        return Result.ok(Boolean.TRUE);
    }

    @Override
    public Result<Set<Role>> findRolePermissionsByUserId(Long userId) {

        if (userId == null){

            LOGGER.error("查询角色对应的菜单权限userId:{} 参数为空", userId);
            return Result.fail(AdminErrorMsgEnum.REQUEST_PARAMS_IS_EMPTY);
        }

        User user = userDao.findUserByUserId(userId);
        if (user == null){

            LOGGER.error("当前userId:{} 查询对应用户角色不存在", userId);
            return Result.fail(AdminErrorMsgEnum.CURRENT_USER_NOT_EXIST);
        }

        if (!user.getStatus().equals(AdminConst.START_STATUS)){

            LOGGER.error("当前用户状态Status：{}不是启用状态", user.getStatus());
            return Result.fail(AdminErrorMsgEnum.CURRENT_USER_STATUS_STOP);
        }

        List<UserRole> userRoleList = userRoleDao.findUserRoleByUserId(userId);
        List<Long> roleIdList = new ArrayList<>();

        if (CollectionUtils.isEmpty(userRoleList)){

            LOGGER.error("根据用户id查询对应的用户角色数据为空code:002,userId:{}",userId);
            return Result.fail(AdminErrorMsgEnum.CURRENT_USER_NOT_EXIST);
        }

        userRoleList.forEach(u -> {

            Long roleId = u.getRoleId();
            roleIdList.add(roleId);
        });

        List<Role> roleList = roleDao.findRoleByRoleIds(roleIdList);
        List<Long> roleIdsItemList = new ArrayList<>();

        if (CollectionUtils.isEmpty(roleList)){

            LOGGER.error("根据用户角色查询对应的角色数据为空,userId:{}, roleIdsList:{}",userId,roleIdList);
            return Result.fail(AdminErrorMsgEnum.CURRENT_USER_NOT_EXIST);
        }

        for (Role role : roleList){

            Long roleId = role.getId();
            List<Long> menuIdsItemList = new ArrayList<>();
            List<RoleMenu> roleMenuList = roleMenuDao.findRoleMenuByRoleId(roleId);

            LOGGER.info("角色roleId：{}，userId: {} 查询对应的角色权限数据roleMenuList:{}", roleId, userId, roleMenuList);

            if (CollectionUtils.isEmpty(roleMenuList)){
                LOGGER.error("当前角色roleId:{}, userId:{} 查询对应角色菜单权限不存在！", roleId, userId);
                continue;
            }

            roleMenuList.stream().forEach(menu -> {
                menuIdsItemList.add(menu.getMenuId());
            });

            List<Menu> menuList = menuDao.findMenuByMenuIds(menuIdsItemList);
            Set<Menu> menuSet = menuList.stream().filter(menu -> menu.getStatus().equals(AdminConst.START_STATUS)).collect(Collectors.toSet());

            LOGGER.info("当前userId：{}， roleId: {} 查询对应的菜单menuId：{}", userId, roleId, menuSet);
            role.setMenus(menuSet);
        }

        Set<Role> set = roleList.stream().filter(role -> role.getStatus().equals(AdminConst.START_STATUS)).collect(Collectors.toSet());

        LOGGER.info("查询用户userId:{}对应角色权限数据set:{}", userId, set);

        return Result.ok(set);
    }

    @Override
    public Result<DataPage<Role>> findRoleByPage(RoleRequest request) {

        Integer pageNo = request.getPageNo();
        Integer pageSize = request.getPageSize();

        LOGGER.info("从第{}页开始, 显示{}条", pageNo, pageSize);

        if (StringUtils.isBlank(request.getAsc()) || StringUtils.isBlank(request.getOrderByColumn())){
            request.setAsc("desc");
            request.setOrderByColumn("create_date");
        }

        DataPage<Role> dataPage = new DataPage<>(pageNo, pageSize);
        Map<String, Object> map = BeanUtil.beanToMap(request);
        map.put("start", dataPage.getStartIndex());
        map.put("offset", dataPage.getPageSize());
        //map.put("")

        long roleCount = roleDao.findRoleCountByPage(map);
        List<Role> list = roleDao.findRoleListByPage(map);

        LOGGER.info("查询用户大小数量TotalCount:{}", roleCount);

        dataPage.setTotalCount(roleCount);
        dataPage.setDataList(list);

        return Result.ok(dataPage);
    }

    @Override
    public Result<Role> findRoleById(Long id) {

        if (id == null){
            LOGGER.error("用户id为空");
            return Result.fail(AdminErrorMsgEnum.REQUEST_PARAMS_IS_EMPTY);
        }

        Role role = roleDao.findRoleById(id);

        User createUserInRole = userDao.findUserByUserId(role.getCreateBy());
        User updateUserInRole = userDao.findUserByUserId(role.getUpdateBy());

        role.setCreateUser(createUserInRole);
        role.setUpdateUser(updateUserInRole);

        LOGGER.info("当前用户为: {}", role);
        return Result.ok(role);
    }

    @Override
    public Result<Integer> updateRole(RoleRequest roleRequest) {

        if (roleRequest.getId() == null){
            LOGGER.error("修改用户信息id参数为空");
            return Result.fail(AdminErrorMsgEnum.REQUEST_PARAMS_IS_EMPTY);
        }

        // 插入
        roleRequest.setUpdateDate(new Date());

        Long roleId = roleRequest.getId();
        Role role = roleDao.findRoleById(roleId);
        if (role == null){
            LOGGER.error("当前修改用户不存在, roleId:{}", roleId);
            return Result.fail(AdminErrorMsgEnum.CURRENT_MENU_NOT_EXIST);
        }

        Role updateRole = new Role();
        BeanUtils.copyProperties(roleRequest, updateRole);

        Integer status = roleDao.updateSelective(updateRole);
        if (status != 1){
            LOGGER.error("更新用户失败,roleId:{}", roleId);
            return Result.fail(AdminErrorMsgEnum.CURRENT_USER_OPERATION_FAIL);
        }
        return Result.ok(status);
    }

    @Override
    public Result<Integer> deleteRoleById(Long id) {

        if(id == null){
            LOGGER.error("删除用户数据请求id为空");
            return Result.fail(AdminErrorMsgEnum.REQUEST_PARAMS_IS_EMPTY);
        }

        Integer deleteUserStatus = roleDao.deleteRoleById(id);

        if (deleteUserStatus != 1){
            LOGGER.error("用户id:{}删除数据失败", id);

        }

        return Result.ok(deleteUserStatus);
    }

    @Override
    public Result<Integer> deleteRoleListById(List<Long> list) {

        Integer count = roleDao.deleteRoleListById(list);

        if (count == null || count < 1){
            LOGGER.error("当前用户删除错误，请重试！");
            return Result.fail(AdminErrorMsgEnum.CURRENT_USER_ROLE_NOT_EXIST);
        }

        LOGGER.info("操作成功：删除了id为: {}，用户", list);
        return Result.ok(count);
    }

    @Override
    public Result saveRole(RoleRequest roleRequest) {

        if (roleRequest == null){
            LOGGER.error("该角色不存在，请刷新页面后尝试");
            return Result.fail(AdminErrorMsgEnum.CURRENT_USER_ROLE_NOT_EXIST);
        }

        Role role = new Role();
        BeanUtils.copyProperties(roleRequest, role);

        String name = role.getName();
        String title = role.getTitle();
        Integer status = role.getStatus();

        Date date = new Date();
        role.setCreateDate(date);
        role.setCreateBy(1L);

        if (StringUtils.isBlank(name) || StringUtils.isBlank(title) ||
                (status == null)){

            LOGGER.error("信息请勿留空，或者状态异常");
            return Result.fail(AdminErrorMsgEnum.CURRENT_USER_OPERATION_FAIL);
        }

        Integer count = roleDao.insertSelective(role);
        return Result.ok(count);
    }

    @Transactional
    @Override
    public Result authPermissions(RoleMenu roleMenu) {

        if (roleMenu == null){
            LOGGER.error("未找到该角色下的菜单");
            return Result.fail(AdminErrorMsgEnum.CURRENT_ROLE_MENU_NOT_EXIST);
        }

        roleDao.deleteAuthPermissionsByRoleIdAndMenuIds(roleMenu);

        if (roleMenu.getAuthMenuIds().size() < 1){
            return Result.ok(roleMenu);
        }

        Integer inertCount = roleDao.authPermissions(roleMenu);
        if (inertCount < 1){
            LOGGER.error("添加菜单错误！inertCount:{}", inertCount);
            throw Ex.business(AdminErrorMsgEnum.DATABASE_OPTION_EXCEPTION);
        }

        LOGGER.info("添加成功！roleId:{}, menuListIds:{}", roleMenu.getRoleId(), roleMenu.getAuthMenuIds());

        return Result.ok(roleMenu);
    }

    @Override
    public Result<List<User>> findUserByRoleId(Long id) {

        if (id == null){
            LOGGER.error("当前用户id:{}不存在", id);
            return Result.fail(AdminErrorMsgEnum.CURRENT_USER_NOT_EXIST);
        }

        List<UserRole> userIdsByRoleId = userRoleDao.findUserIdsByRoleId(id);

        if (CollectionUtils.isEmpty(userIdsByRoleId)){
            LOGGER.error("无当前角色");
            return Result.fail(AdminErrorMsgEnum.CURRENT_USER_ROLE_NOT_EXIST);
        }

        List<User> userList = new ArrayList<>();

        for (UserRole userRole : userIdsByRoleId) {
            userList.add(userDao.findUserByUserId(userRole.getUserId()));
        }

        LOGGER.info("当前角色下的用户为UserList:{}", userList);

        return Result.ok(userList);
    }

    @Override
    public Result enableRoleStatus(List<Long> ids) {

        if (ids == null || ids.size() < 1){
            LOGGER.error("角色列表为空！");
            return Result.fail(AdminErrorMsgEnum.ROLE_LIST_NOT_EXIST);
        }

        Integer count = roleDao.updateRoleStatusByRoleIds(ids, 1);

        if (count < 1){
            LOGGER.error("无意义的参数");
            return Result.fail(AdminErrorMsgEnum.MEANINGLESS_PARAMETER);
        }

        LOGGER.info("修改状态成功，当前状态为启用状态，修改了:{}条数据", count);

        return Result.ok(count);
    }

    @Override
    public Result disableRoleStatus(List<Long> ids) {

        if (ids == null || ids.size() < 1){
            LOGGER.error("角色列表为空！");
            return Result.fail(AdminErrorMsgEnum.ROLE_LIST_NOT_EXIST);
        }

        Integer count = roleDao.updateRoleStatusByRoleIds(ids, 2);

        if (count < 1){
            LOGGER.error("无意义的参数");
            return Result.fail(AdminErrorMsgEnum.MEANINGLESS_PARAMETER);
        }

        LOGGER.info("修改状态成功，当前状态为启用状态，修改了:{}条数据", count);

        return Result.ok(count);
    }


}
